//
// Created by Martin on 2022/10/1.
//

#include <iostream>

using namespace std;

#if 0
typedef replace_type< void*, void, int >::type t1; // int*
typedef replace_type<
          int const*[10]
        , int const
        , long
>::type t2; // long* [10]

typedef replace_type<
          char& (*)(char*)
        , char&
        , long&
>::type t3; // long& (*)(long&)
#endif

#if 0
// replace_type_imp主模板
template<typename C, typename X, typename Y, bool>
struct replace_type_imp
{
};

template<typename C, typename X, typename Y>
struct replace_type
{
    static bool const value = std::is_same<C, X>::value;
    typedef typename replace_type_imp<C, X, Y, value>::type type;
};

// 偏特化void
// C: void const*, X: void const
template<typename C, typename X, typename Y>
struct replace_type_imp<C(), X, Y, false>
{
    typedef typename replace_type<C, X, Y>::type type();
};

// 偏特化T*
// C: T*, X: T
template<typename C, typename X, typename Y>
struct replace_type_imp<C*, X, Y, false>
{
    typedef typename replace_type<C*, X, Y>::type type;
};


// value为true
template<typename C, typename X, typename Y>
struct replace_type_imp<C, X, Y, true>
{
    typedef C type;
};

#endif


#if 0

// replace_type主模板
template<typename TC, typename TX, typename TY>
struct replace_type
{
    typedef TC type;
};

// 偏特化TC*
// e.g. TC: void*, TX: void, TY:long
// ::type = long*
template<typename TC, typename TY>
struct replace_type<TC*, TC, TY>
{
    typedef typename std::add_pointer<TY>::type type;
};

template<typename TC, typename TY>
struct replace_type<TC* const, TC, TY>
{
    typedef typename std::add_pointer<std::add_const<TY>>::type type;
};

// 偏特化TC*[]
template<typename TC, typename TY>
struct replace_type<TC*[], TC, TY>
{
    typedef typename std::add_pointer<TY>::type type[];
};

// 偏特化TC const*[]
template<typename TC, typename TY>
struct replace_type<TC const*[], TC, TY>
{
    typedef typename std::add_pointer<std::add_const<TY>>::type type[];
};

// 偏特化TC*[N]
template<typename TC, typename TY, int N>
struct replace_type<TC*[N], TC, TY>
{
    typedef typename std::add_pointer<TY>::type type[N];
};

// 偏特化TC[]
template<typename TC, typename TY>
struct replace_type<TC[], TC, TY>
{
    typedef TY type[];
};

// 偏特化TC[N]
template<typename TC, typename TY, int N>
struct replace_type<TC[N], TC, TY>
{
    typedef TY type[N];
};

// 偏特化TC&
// e.g. TC: int&, TX: int, TY: long
// => long&
template<typename TC, typename TY>
struct replace_type<TC&, TC, TY>
{
    typedef typename std::add_lvalue_reference<TY>::type type;
};

// 偏特化TC const
// e.g. TC:int const, TX: int, TY: long
// => long const
template<typename TC, typename TY>
struct replace_type< TC const, TC, TY>
{
    typedef typename std::add_const<TY>::type type;
};

// 偏特化TC (*)(TC)
// e.g. TC: int *(int), TX: int, TY: long
template<typename TC, typename TY>
struct replace_type<TC (*)(TC), TC, TY>
{
    template<typename T = TY(*)(TY)>
    struct replace_type_detail
    {
        typedef typename T type;
    };
    typedef typename replace_type_detail<>::type type;
};

#endif

template<typename TC, typename TX, typename TY, bool same>
struct replace_type_impl;

// 主模板
template<typename TC, typename TX, typename TY>
struct replace_type
{
    static const bool value = std::is_same<TC, TX>::value;
    typedef typename replace_type_impl<TC, TX, TY, value>::type type;
};

// 偏特化TC*
// TC: int*, TX: int, TY: long
// type => long*
template<typename TC, typename TX, typename TY>
struct replace_type_impl<TC*, TX, TY, false>
{
    typedef typename replace_type<TC, TX, TY>::type* type;
};

// 偏特化TC[]
template<typename TC, typename TX, typename TY>
struct replace_type_impl<TC[], TX, TY, false>
{
    typedef typename replace_type<TC, TX, TY>::type type[];
};

// 偏特化TC[N]
template<typename TC, typename TX, typename TY, int N>
struct replace_type_impl<TC[N], TX, TY, false>
{
    typedef typename replace_type<TC, TX, TY>::type type[N];
};

// 偏特化TC&
template<typename TC, typename TX, typename TY>
struct replace_type_impl<TC&, TX, TY, false>
{
    typedef typename replace_type<TC, TX, TY>::type& type;
};

// 偏特化函数
// TC接受0个参数
template<typename TC, typename TX, typename TY>
struct replace_type_impl<TC(), TX, TY, false>
{
    typedef typename replace_type<TC, TX, TY>::type type();
};

// 接受1个参数, 作为多参的边界条件
template<typename TC, typename TX, typename TY, typename Arg>
struct replace_type_impl<TC(Arg), TX, TY, false>
{
    typedef typename replace_type<TC, TX, TY>::type type(typename replace_type<Arg, TX, TY>::type);
};

// 接受2个参数
template<typename TC, typename TX, typename TY, typename Arg1, typename Arg2>
struct replace_type_impl<TC(Arg1, Arg2), TX, TY, false>
{
    typedef typename replace_type<TC, TX, TY>::type type(typename replace_type<Arg1, TX, TY>::type,
                                                         typename replace_type<Arg2, TX, TY>::type);
};

// 接受多个参数
template<typename TC, typename TX, typename TY, typename... Args>
struct replace_type_impl<TC(Args...), TX, TY, false>
{
    typedef typename replace_type<TC, TX, TY>::type type(typename replace_type<Args, TX, TY>::type...);
};

// TC与TX完全相同, TY替换TX
template<typename TC, typename TX, typename TY>
struct replace_type_impl<TC, TX, TY, true>
{
    typedef TY type;
};

#if __cplusplus < 201700L
template<typename T, typename U>
inline constexpr bool is_same_v = std::is_same<T, U>::value;
#endif

static void test_replace_type()
{
    typedef void(*VoidParamFunc)();

    cout << boolalpha;
    // 以下全部打印true
    cout << is_same_v<replace_type<void*, void, int>::type, int*> << endl;
    cout << is_same_v<replace_type<int, int, long>::type, long> << endl;
    cout << is_same_v<replace_type<int const, int const, long>::type, long> << endl;
//    cout << is_same_v<replace_type<int const, int, long>::type, long const> << endl;
//    cout << is_same_v<replace_type<int const[10], int, long>::type, long const [10]> << endl;
    cout << is_same_v<replace_type<int const[10], int const, long>::type, long[10]> << endl;
    cout << is_same_v<replace_type<int *[10], int , long>::type, long*[10]> << endl;
    cout << is_same_v<replace_type<int const*[10], int const, long>::type, long*[10]> << endl;
    cout << is_same_v<replace_type<int&, int, char>::type, char&> << endl;
    cout << is_same_v<replace_type<char(), char, int>::type, int()> << endl;
    cout << is_same_v<replace_type<char(char), char, int>::type, int(int)> << endl;
    cout << is_same_v<replace_type<char*(char*), char*, int>::type, int(int)> << endl;
    cout << is_same_v<replace_type<char*(char*), char, int>::type, int*(int*)> << endl;
    cout << is_same_v<replace_type<char&(char&), char&, int>::type, int(int)> << endl;
    cout << is_same_v<replace_type<char&(char), char, int>::type, int&(int)> << endl;
    cout << is_same_v<replace_type<char(char, char), char, int>::type, int(int, int)> << endl;
    cout << is_same_v<replace_type<char(char, char, char), char, int>::type, int(int, int, int)> << endl;
}

int main()
{
    test_replace_type();
    return 0;
}
